class Crypto {
    constructor() {
        this.key = CryptoJS.enc.Hex.parse('e10adc3949ba59abbe56e057f20f883e');
        this.iv = CryptoJS.enc.Hex.parse('1234567890abcdef1234567890abcdef');
        this.opinion = {
            iv: this.iv,
            padding: CryptoJS.pad.ZeroPadding,
        };
    }

    enCode(text) {
        return CryptoJS.AES.encrypt(text, this.key, this.opinion).toString();
    }

    deCode(encrypted) {
        return CryptoJS.AES.decrypt(encrypted, this.key, this.opinion).toString(CryptoJS.enc.Utf8);
    }
}

((w) => {
    function fixStatusBar(elem = '.fxj-header', baseTop = 0) {
        let element = null;
        if (typeof elem === 'string') {
            element = document.querySelector(elem);
        } else {
            element = elem;
        }
        let height = element.clientHeight;
        if (fxj.getSystemType() === 'ios') {
            element.style.paddingTop = 20 + 'px';
            height += 20;
        } else {
            element.style.paddingTop = 25 + 'px';
            height += 25;
        }
        height += baseTop;
        element.style.maxHeight = height + 'px';
        element.style.minHeight = height + 'px';
    }

    function fixContainer(container, baseTop = 0, footer = '', footerOffset = 0) {
        let element = typeof container === 'string' ? document.querySelector(container) : container;
        let headH = 40;
        if (fxj.getSystemType() === 'ios') {
            headH += 20;
        } else {
            headH += 25;
        }
        if (footer) {
            element.style.marginBottom = document.querySelector(footer).clientHeight + footerOffset + 'px';
        }
        headH += baseTop;
        element.style.marginTop = headH + 'px';
    }

    function getSystemType() {
        const agent = navigator.userAgent;
        let type = '';
        if (/(iPhone)|(Mac OS X)/i.test(agent)) {
            type = 'ios';
        } else {
            type = 'android';
        }
        getSystemType = function () {
            return type;
        };
        return type;
    }

    function getFixOffset() {
        let offset = 0;
        if (getSystemType() === 'ios') {
            offset = 20;
        } else {
            offset = 25;
        }
        getFixOffset = function () {
            return offset;
        };
        return offset;
    }

    function getHtmlName(url) {
        return /(?:\b|\\)(\w*).html/.exec(url)[1];
    }

    function isTel(str) {
        return /1\d{10}/.test(str) && str.length === 11;
    }

    function trimAll(str) {
        str = str.replace(/\s/gi, '');
        str = str.trim();
        return str;
    }

    function isNumber(str) {
        return /\d*/.test(str);
    }

    function verifyIpt() {
        const typeMap = {
            'tel': isTel,
            'number': isNumber,
        };
        return (ipt, iptType) => {
            return typeMap[iptType](ipt);
        };
    }

    function fixLayout(header = '.fxj-header', main = '#main') {
        fxj.fixStatusBar(header);
        fxj.fixContainer(main);
    }

    function fixImgUrl(url) {
        if (!/https?/.test(url)) {
            url = 'http://www.fxj178.com/' + url;
        }
        return url;
    }

    async function getAuthCode(tel) {
        const result = await ajax({
            url: 'home/userLogin/getCode',
            type: 'POST',
            data: {
                phone: tel,
            },
        });
        if (result.err === 0) {
            toast('发送成功');
            return true;
        } else {
            toast(result.msg ? result.msg : result.message ? result.message : '发送失败');
            return false;
        }
    }

    function getUserLocation() {
        return new Promise(resolve => {
            navigator.geolocation.getCurrentPosition(
                position => {
                    resolve([position.coords, true]);
                },
                err => {
                    resolve([Number(err.code), false]);
                }, {
                    enableHighAccuracy: true,
                    timeout: 2e4,
                },
            );
        });
    }

    function closeWin(winName = /html\/(.+)\.html/.exec(location.pathname)[1]) {
        if (apiOk()) {
            api.closeWin({
                name: winName,
            });
        } else {
            history.back();
        }
    }

    function closeFrame(frameName) {
        if (apiOk()) {
            api.closeFrame({
                name: frameName,
            });
        }
    }

    function readFile(file) {
        return new Promise((resolve, reject) => {
            const reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onload = function (evt) {
                resolve(evt.target.result);
            };
            reader.onerror = function (e) {
                console.error(e);
                reject(false);
            };
        });
    }

    function getSearch() {
        return {
            get(key) {
                const search = decodeURIComponent(location.search).slice(1);
                const searchList = search.split('&');
                const searchMap = {};
                forEach(searchList, (s) => {
                    let [k, v] = s.split('=');
                    searchMap[k] = v;
                });
                const ret = searchMap[key];
                if (ret) return ret;
                return '';
            },
        };
    }

    function hasSearch() {
        return location.search !== '';
    }

    function alert({
        title = '提示',
        msg = '提示信息',
        btnLeft = '确认',
        btnRight = '取消',
        leftCallback,
        rightCallback,
        btn = 2,
    }) {
        if (apiOk() && btn === 2) {
            if (btn === 2) {
                api.confirm({
                    title,
                    msg,
                    buttons: [btnRight, btnLeft],
                }, function (res) {
                    const {
                        buttonIndex,
                    } = res;
                    if (buttonIndex === 2) {
                        leftCallback && leftCallback();
                    } else {
                        rightCallback && rightCallback();
                    }
                });
            } else if (btn === 1) {
                api.alert({
                    title,
                    msg,
                    buttons: [btnLeft],
                }, function () {
                    leftCallback && leftCallback();
                });
            }
        } else {
            const div = document.createElement('div');
            div.innerHTML = `
                <section class="fxj-dialog-container">
                    <div class="fxj-dialog-box">
                        <div class="fxj-dialog-title">${title}</div>
                        <div class="fxj-dialog-des">${msg}</div>
                        <div class="fxj-dialog-btn-group">
                            <button class="fxj-dialog-affirm-left ${btn === 2 ? 'border' : ''}">${btnLeft}</button>
                            ${btn === 2 ? `<button class="fxj-dialog-affirm-right">${btnRight}</button>` : ''}
                        </div>
                    </div>
                </section>`.trim();
            const closeF = function () {
                div.parentNode.removeChild(div);
            };
            div.querySelector('.fxj-dialog-affirm-left').addEventListener('click', () => {
                leftCallback && leftCallback();
                closeF();
            });
            btn === 2 && div.querySelector('.fxj-dialog-affirm-right').addEventListener('click', () => {
                rightCallback && rightCallback();
                closeF();
            });
            document.body.appendChild(div);
        }
    }

    function loading({
        des = '',
        cb,
        noBg = false,
        title = '',
    } = {}) {
        let close = null;
        if (apiOk()) {
            api.showProgress({
                title,
                text: des,
                modal: false,
            });
            close = () => {
                api.hideProgress();
            };
        } else {
            close = () => {

            };
        }
        cb && cb(close);
        return close;
    }

    async function getAuthCodeBtn(elem, tel) {
        if (tel.trim() === '') {
            toast('请输入手机号码');
            return;
        }
        if (!fxj.verifyIpt(tel, 'tel')) {
            toast('请输入正确格式的手机号码');
            return;
        }
        let s = 60;
        (function down() {
            setTimeout(() => {
                s--;
                elem.innerHTML = `${s}s后重发`;
                elem.classList.add('disable');
                if (s > 0) {
                    down();
                } else {
                    elem.classList.remove('disable');
                    elem.innerHTML = '获取验证码';
                }
            }, 1000);
        })();
        const result = await fxj.api.getAuthCode(tel);
        if (!result) {
            s = 0;
        }
    }

    async function getOldPhone() {
        const result = await ajax({
            url: 'home/userCenter/getOldPhone',
            data: {
                token: localStorage.getItem('token'),
            },
            type: 'POST',
        });
        if (result.err !== 0) {
            return ([result.msg, false]);
        }
        return ([result.data.phone, true]);
    }

    async function collectHouse(id) {
        const close = fxj.dialog.loading({
            noBg: true,
        });
        const res = await ajax({
            url: 'home/userCenter/collectHouse',
            data: {
                houseId: id,
            },
        });
        close();
        return res;
    }

    function _prompt({
        title = '',
        msg = '',
        text = '',
        type = '',
        buttons = ['取消', '确定'],
    }) {
        return new Promise(resolve => {
            api.prompt({
                title,
                msg,
                text,
                type,
                buttons,
            }, (ret) => {
                resolve(ret);
            });
        });
    }

    async function prompt({
        title = '提示',
        msg = '',
        text = '',
        type = '',
        buttons = ['取消', '确定'],
    }) {
        let txt = '';
        if (!apiOk()) {
            txt = window.prompt(msg);
        } else {
            const ret = await _prompt({
                title,
                msg,
                text,
                type,
                buttons,
            });
            const {
                buttonIndex,
            } = ret;
            if (buttonIndex === 2) {
                txt = ret.text;
            }
        }
        if (isExist(txt)) {
            return txt;
        }
        return false;
    }

    function isContainElement(el, fn) {
        const clientRect = el.getBoundingClientRect();
        if (clientRect.top <= screen.availHeight && clientRect.left <= screen.availWidth) {
            fn && fn(el);
        }
    }

    function isMobilePhone() {
        return /mobile/i.test(navigator.userAgent);
    }

    function reqSign() {
        return new Promise(resolve => {
            $.ajax({
                url: fxj.apiServerAddress + 'home/index/getTime13',
                type: 'GET',
                dataType: 'json',
                success: (res) => {
                    resolve(res.msg);
                },
                error: (e) => {
                    console.error(JSON.stringify(e));
                },
            });
        });
    }

    // noinspection JSUnusedGlobalSymbols
    w.fxj = {
        api: {
            getAuthCode,
            getAuthCodeBtn,
            getUserLocation,
            getOldPhone,
            collectHouse,
            reqSign,
        },
        dialog: {
            alert,
            loading,
            prompt,
        },
        isMobilePhone,
        isContainElement,
        fixStatusBar,
        fixContainer,
        getSystemType,
        getHtmlName,
        verifyIpt: verifyIpt(),
        trimAll,
        fixLayout,
        fixImgUrl,
        serverAddress: 'http://www.fxj178.com/',
        apiServerAddress: 'http://appv2.fxj178.com/', //http://192.168.0.109/appphp/
        deBug: /(^localhost:8080$)|(^127.0.0.1:5500)/.test(location.host), // , // false,
        closeWin,
        closeFrame,
        getSearch,
        hasSearch,
        readFile,
        getFixOffset,
    };
})(window);

function openWin({
    url,
    pageParam,
    bounces = false,
    progress = {
        type: 'default',
    },
}) {
    if (typeof api !== 'undefined') {
        api.openWin({
            name: fxj.getHtmlName(url),
            url,
            pageParam,
            historyGestureEnabled: true,
            vScrollBarEnabled: false,
            hScrollBarEnabled: false,
            bounces,
            progress,
            animation: {
                type: 'push',
                subType: 'from_right',
                duration: 400,
            },
            delay: 0,
            softInputMode: 'resize',
        });
    } else {
        location.assign(url);
    }
}

function openFrame({
    url,
    pageParam,
    bounces = false,
    rect,
}) {
    api.openFrame({
        name: fxj.getHtmlName(url),
        url,
        vScrollBarEnabled: false,
        hScrollBarEnabled: false,
        pageParam,
        bounces,
        rect,
        bgColor: '#fff',
        softInputMode: 'fade',
        animation: {
            type: 'fade',
            duration: 300,
        },
    });
}

function ajax({
    url = '',
    type = 'POST',
    data = {},
    processData = true,
}) {
    return new Promise(async resolve => {
        const token = localStorage.getItem('token');
        if (token && processData) {
            data.token = token;
        }
        let sign = await fxj.api.reqSign();
        const hp = {
            'app-type': fxj.deBug ? 'ios' : api.systemType,
            did: fxj.deBug ? '321' : api.deviceId,
            version: fxj.deBug ? '0.0.0' : api.appVersion,
        };
        const headerPromise = $.param(hp);
        const si = hp;
        si.time = sign;
        sign = $.param(si);
        $.ajax({
            url: /http(s)?:\/\//.test(url) ? url : fxj.apiServerAddress + url,
            type,
            data,
            dataType: 'json',
            processData,
            headers: {
                'Content-Type': processData ? 'application/x-www-form-urlencoded' : false,
                'header-promise': new Crypto().enCode(headerPromise),
                sign: new Crypto().enCode(sign),
            },
            error(xhr, textStatus, errorThrown) {
                console.log('----请求 ' + url + ' 失败----');
                console.log(`time: ${new Date().toLocaleString()}`)
                console.log(`[ ${xhr.readyState} : ${xhr.status} : ${xhr.statusText} ]`);
                console.log('responseText: [' + xhr.responseText + ' ]');
                console.log('textStatus: ' + textStatus);
                console.log('errorThrown:' + errorThrown);
                console.log(JSON.stringify(data));
                console.log('----结束----');
            },
            success(data) {
                resolve(data);
            },
        });
    });
}

/**
 *  @description 下拉刷新
 */
function setCustomRefreshHeaderInfo(cb, delay = 1000) {
    api.setCustomRefreshHeaderInfo({
        bgColor: '#C0C0C0', //（可选项）字符串类型；下拉刷新的背景设置，支持 rgb、rgba、#，该背景大小同当前 window 或 frame 的宽高；默认：#C0C0C0
        refreshHeaderHeight: 60, //(可选项)数字类型；下拉高度达到一定阈值；默认：60(该参数只支持ios)
        loadAnimInterval: 200, //(可选项)数字类型；单位为毫秒,图片播放时间间隔
        /*image: {                                        //（可选项）JSON 对象类型；下拉刷新相关图片设置；若不传则使用默认图标
            pull: ['fs://t1.png', 'fs://t2.png'],    //（可选项）数组类型；组成下拉过程的动画关键帧图片数组，这组图片随下拉高度同步放大缩小，同时自动播放关键帧图片：每下拉一定距离（阈值/图片数量），播放一帧关键帧图片；图片规格为正方形，如：50*50、100*100；若不传则使用默认图标
            load: ['fs://t1.png', 'fs://t2.png']     //（可选项）数组类型；组成下拉刷新加载状态动画的关键帧图片数组，图片为正方形的，如：50*50、100*100，建议开发者传大小合适的图片以适配高分辨率手机屏幕；若不传则使用默认图标
        },*/
        isScale: true //（可选项）布尔类型；播放下拉过程中的关键帧动画时，是否同时添加等比同步缩放效果；默认值：true
    }, (ret, err) => {
        cb(ret, err);
        setTimeout(() => {
            api.refreshHeaderLoadDone();
        }, delay);
    });
}

function pipe(x, ...func) {
    return func.reduce((accumulator, currentValue) =>
        currentValue(accumulator), x);
}

function goPage(url, {
    bounces = false,
    before = () => true,
    data,
    localData,
} = {}) {
    if (data) {
        let qs = '?';
        for (let [k, v] of Object.entries(data)) {
            const kv = `${k}=${v}`;
            qs = qs.includes('=') ? `${qs}&${kv}` : qs + kv;
        }
        url += qs;
    }
    if (localData) {
        for (const [k, v] of Object.entries(localData)) {
            localStorage.setItem(k, JSON.stringify(v));
        }
    }
    before() && openWin({
        url,
        bounces,
    });
}

function go(url, {
    before = () => true,
    data,
    localData,
} = {}) {
    if (data) {
        let qs = '?';
        for (let [k, v] of Object.entries(data)) {
            const kv = `${k}=${v}`;
            qs = qs.includes('=') ? `${qs}&${kv}` : qs + kv;
        }
        url += qs;
    }
    if (localData) {
        for (const [k, v] of Object.entries(localData)) {
            localStorage.setItem(k, JSON.stringify(v));
        }
    }
    before() && location.assign(url);
}

function closeToWin(name = 'root') {
    if (apiOk()) {
        api.closeToWin({
            name,
        });
    }
}

(() => {
    window.addEventListener('DOMContentLoaded', () => {
        forEach(document.querySelectorAll('back'), e => {
            e.outerHTML = `
                <span class="back" onclick="fxj.closeWin()">
                    <svg class="icon" aria-hidden="true">
                        <use xlink:href="#icon-jiantou"></use>
                    </svg>
                </span>`.trim();
        });
        forEach(document.querySelectorAll('backh'), e => {
            e.outerHTML = `
                <span class="back" onclick="history.back()">
                    <svg class="icon" aria-hidden="true">
                        <use xlink:href="#icon-jiantou"></use>
                    </svg>
                </span>`.trim();
        });
    }, {
        once: true,
    });
})();

function forEach(args, fn) {
    if (args && args.length > 0) {
        for (let i = 0; i < args.length; i++) {
            try {
                fn(args[i], i, args);
            } catch (e) {
                console.error('参数:', args, '  当前参数:', args[i], '  错误描述:', e);
                catchError(e);
            }
        }
    }
}

function apiOk() {
    return typeof api !== 'undefined';
}

function toast(msg = '', cb, time = 2000, global = false) {
    if (apiOk()) {
        api.toast({
            msg,
            duration: time,
            location: 'bottom',
            global,
        });
    } else {
        mui.toast(msg, {
            duration: time - 1,
        });
    }
    return new Promise(resolve => {
        setTimeout(() => {
            resolve(true);
            cb && cb();
        }, time);
    });
}

function isToBottom(offsetBottom = 0, cb = (ok, el, evt) => {}, timeOut = 200) {
    const loadBox = document.getElementById('loadMore');
    let id = null;
    window.addEventListener('touchmove', (e) => {
        const winHeight = window.screen.height;
        id && clearTimeout(id);
        id = setTimeout(() => {
            cb && cb(winHeight > (loadBox.getBoundingClientRect().top - offsetBottom), loadBox, e);
        }, timeOut);
    });
}

function isExist(x) {
    return x !== '' && x !== null && x !== undefined;
}

function isTruth(x) {
    return isExist(x) && x !== false;
}

function isIpad() {
    const ipad = /ipad/i.test(navigator.userAgent);
    isIpad = () => {
        return ipad;
    };
    return ipad;
}

function getAndroidVersion() {
    const version = /android\s([0-9])\./i.exec(navigator.userAgent);
    if (isExist(version) && version.length >= 2) {
        return Number(version[1]);
    }
    return false;
}

function getIosVersion() {
    const version = /version\/(\d)./i.exec(navigator.userAgent);
    if (isExist(version) && version.length >= 2) {
        return +version[1];
    }
    return false;
}

function catchError(error) {
    if (isTestVersion()) {
        location.assign('http://stackoverflow.com/search?q=[js] + ' + error.message);
    }
}

function isTestVersion() {
    return api.appVersion.includes('00.00.');
}

function typeOf(x) {
    return /\s(\w*)]/.exec(Object.prototype.toString.call(x))[1];
}

function log(...arg) {
    let s = '';
    forEach(arg, a => {
        try {
            s += JSON.stringify(a);
        } catch (e) {
            s += a.toString();
        }
        s += '    ';
    });
    console.log(s);
}